#lang racket


(require "../misc.rkt"
         "../point-matrix.rkt")

(require "domain.rkt"
         
         "parametric-arc.rkt"
         "parametric-curve.rkt"
         "parametric-circumference.rkt"
         
         "parametric-surface.rkt"
         "parametric-straight-line.rkt"
         "parametric-surface-plane.rkt"
         "parametric-surface-sinwave.rkt"
         
         "parametrize.rkt"
         "patch.rkt"
         
         "segment.rkt"
         "segmentate.rkt")


(provide (all-from-out "domain.rkt"
                       "patch.rkt"
                       "parametric-arc.rkt"
                       "segment.rkt"
                       "segmentate.rkt")
         
         make-simple-parametric-curve
         parametric-curve-object
         parametric-curve-tangent
         parametric-curve-normal
         parametric-curve-binormal
         
         circumference-radius
         
         straight-line-start
         straight-line-end
         
         make-plane
         make-sinwave
         
         parametrize
         
         make-simple-parametric-surface
         parametric-surface-object
         parametric-surface-tangent
         parametric-surface-normal
         
         segmentate-strategy-linear
         segmentate-strategy-integral
         
         segmentate
         points)


(define (points-line
         parametric
         points
         space
         t-strategy
         segmentate-strategy)
  (let ((domains (segmentate-strategy (parametric-curve-domain parametric) points)))
    (map
     (cλ m*p (parametric-curve-transformation parametric))
     (map 
      (space parametric)
      (map t-strategy domains)))))

(define (points-surface
         parametric
         points-u
         points-v
         space
         u-strategy
         v-strategy
         segmentate-strategy)
  (let ((domains-u (segmentate-strategy (parametric-surface-domain-u parametric) points-u))
        (domains-v (segmentate-strategy (parametric-surface-domain-v parametric) points-v)))
    (map
     (cλ m*p (parametric-surface-transformation parametric))
     (flatten
      (for/list ((u (map u-strategy domains-u)))
        (for/list ((v (map v-strategy domains-v)))
          ((space parametric) u v)))))))

(define (points parametric
                points
                (space parametric-curve-object)
                (t-strategy #f)
                (segmentate-strategy (segmentate-strategy-linear)))
  (cond ((parametric-curve? parametric)
         (let ((t-strategy (or t-strategy (t-strategy-min))))
           (points-line parametric points parametric-curve-object t-strategy segmentate-strategy)))
        ((parametric-surface? parametric)
         (let ((u-strategy (or (and t-strategy (first t-strategy)) (u-strategy-min)))
               (v-strategy (or (and t-strategy (second t-strategy)) (v-strategy-min))))
           (points-surface parametric (first points) (second points) parametric-surface-object u-strategy v-strategy segmentate-strategy)))
        (else
         (error 'points "Unhandled parametric object"))))